package cn.iocoder.yudao.module.reading.dal.mysql.record;

import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.reading.dal.dataobject.record.ReadingRecordDO;
import org.apache.ibatis.annotations.Mapper;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 阅读记录 Mapper
 *
 * @author 芋道源码
 */
@Mapper
public interface ReadingRecordMapper extends BaseMapperX<ReadingRecordDO> {

    /**
     * 根据用户ID和绘本ID查询阅读记录
     *
     * @param userId 用户ID
     * @param bookId 绘本ID
     * @return 阅读记录
     */
    default ReadingRecordDO selectByUserIdAndBookId(Long userId, Long bookId) {
        return selectOne(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .eq(ReadingRecordDO::getBookId, bookId));
    }

    /**
     * 根据用户ID查询最近阅读记录
     *
     * @param userId 用户ID
     * @param limit  限制数量
     * @return 阅读记录列表
     */
    default List<ReadingRecordDO> selectRecentByUserId(Long userId, Integer limit) {
        return selectList(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .orderByDesc(ReadingRecordDO::getLastReadAt)
                .last("LIMIT " + limit));
    }

    /**
     * 根据用户ID和日期范围查询阅读记录
     *
     * @param userId    用户ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 阅读记录列表
     */
    default List<ReadingRecordDO> selectByUserIdAndDateRange(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return selectList(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .between(ReadingRecordDO::getLastReadAt, startTime, endTime)
                .orderByDesc(ReadingRecordDO::getLastReadAt));
    }

    /**
     * 统计用户今日阅读绘本数
     *
     * @param userId    用户ID
     * @param startTime 今日开始时间
     * @param endTime   今日结束时间
     * @return 阅读绘本数
     */
    default Long countTodayReadBooks(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        return selectCount(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .between(ReadingRecordDO::getLastReadAt, startTime, endTime));
    }

    /**
     * 统计用户总阅读绘本数
     *
     * @param userId 用户ID
     * @return 总阅读绘本数
     */
    default Long countTotalReadBooks(Long userId) {
        return selectCount(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .eq(ReadingRecordDO::getIsCompleted, true));
    }

    /**
     * 根据绘本集ID查询用户阅读记录
     *
     * @param userId    用户ID
     * @param bookIds   绘本ID列表
     * @return 阅读记录列表
     */
    default List<ReadingRecordDO> selectByUserIdAndBookIds(Long userId, List<Long> bookIds) {
        return selectList(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .in(ReadingRecordDO::getBookId, bookIds));
    }

    /**
     * 清空用户最近阅读记录（按语言）
     *
     * @param userId 用户ID
     * @return 删除数量
     */
    default int deleteRecentByUserId(Long userId) {
        return delete(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId));
    }

    /**
     * 统计用户总阅读时长
     *
     * @param userId 用户ID
     * @return 总阅读时长（秒）
     */
    default Integer sumReadingTimeByUserId(Long userId) {
        List<Object> results = selectObjs(new LambdaQueryWrapperX<ReadingRecordDO>()
                .select(ReadingRecordDO::getReadingTime)
                .eq(ReadingRecordDO::getUserId, userId)
                .isNotNull(ReadingRecordDO::getReadingTime));

        return results.stream()
                .filter(obj -> obj != null)
                .mapToInt(obj -> (Integer) obj)
                .sum();
    }

    /**
     * 统计用户不同绘本数量
     *
     * @param userId 用户ID
     * @return 不同绘本数量
     */
    default Integer countDistinctBooksByUserId(Long userId) {
        // TODO: 实现不同绘本数量统计
        return 0;
    }

    /**
     * 根据用户ID和日期范围统计阅读时长
     *
     * @param userId    用户ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 阅读时长（秒）
     */
    default Integer sumReadingTimeByUserIdAndDateRange(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        List<Object> results = selectObjs(new LambdaQueryWrapperX<ReadingRecordDO>()
                .select(ReadingRecordDO::getReadingTime)
                .eq(ReadingRecordDO::getUserId, userId)
                .between(ReadingRecordDO::getLastReadAt, startTime, endTime)
                .isNotNull(ReadingRecordDO::getReadingTime));

        return results.stream()
                .filter(obj -> obj != null)
                .mapToInt(obj -> (Integer) obj)
                .sum();
    }

    /**
     * 分页查询用户阅读记录
     *
     * @param userId 用户ID
     * @param lang   语言类型
     * @param offset 偏移量
     * @param size   每页大小
     * @return 阅读记录列表
     */
    default List<ReadingRecordDO> selectByUserIdWithPaging(Long userId, String lang, int offset, Integer size) {
        // TODO: 实现分页查询
        return selectList(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId)
                .orderByDesc(ReadingRecordDO::getLastReadAt)
                .last("LIMIT " + offset + ", " + size));
    }

    /**
     * 根据用户ID删除阅读记录
     *
     * @param userId 用户ID
     * @return 删除数量
     */
    default int deleteByUserId(Long userId) {
        return delete(new LambdaQueryWrapperX<ReadingRecordDO>()
                .eq(ReadingRecordDO::getUserId, userId));
    }

}
